#include "logclass.h"

LogClass* LogClass::m_instance = nullptr;
QMutex LogClass::m_mutex;

LogClass* LogClass::getInstance()
{
    if (m_instance == nullptr) {
        QMutexLocker locker(&m_mutex);
        if (m_instance == nullptr) {
            m_instance = new LogClass();
        }
    }
    return m_instance;
}

LogClass::LogClass(QObject *parent) : QObject(parent)
{
    // 初始化日志目录
    m_logDir = QCoreApplication::applicationDirPath() + "/logs/";
    QDir dir(m_logDir);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
    m_currentLogFile = "C:/Users/shafl/Desktop/IoTDeviceManage/src/log/log.txt";
    // 设置最大日志文件大小为10MB
    m_maxLogSize = 10;

    // 初始化数据库
    if (!initDatabase()) {
        qDebug() << "Failed to initialize database!";
    }

    // 检查并轮转日志文件
    checkAndRotateLogFile();
}

LogClass::~LogClass()
{
    if (m_database.isOpen()) {
        m_database.close();
    }
}

bool LogClass::initDatabase()
{
    m_database = QSqlDatabase::addDatabase("QSQLITE", "logConnection");
    m_database.setDatabaseName(m_logDir + "system_logs.db");

    if (!m_database.open()) {
        qDebug() << "Cannot open database:" << m_database.lastError().text();
        return false;
    }

    return createLogTable();
}

bool LogClass::createLogTable()
{
    QSqlQuery query(m_database);
    return query.exec(
        "CREATE TABLE IF NOT EXISTS system_logs ("
        "log_id INTEGER PRIMARY KEY AUTOINCREMENT, "
        "timestamp TEXT NOT NULL, "
        "log_type TEXT NOT NULL, "
        "log_level TEXT NOT NULL, "
        "content TEXT NOT NULL, "
        "user_id INTEGER, "
        "device_id INTEGER, "
        "FOREIGN KEY (user_id) REFERENCES users(user_id), "
        "FOREIGN KEY (device_id) REFERENCES devices(device_id)"
        ")"
    );
}

void LogClass::checkAndRotateLogFile()
{
    QString dateStr = QDateTime::currentDateTime().toString("yyyy-MM-dd");
    //m_currentLogFile = m_logDir + "system_" + dateStr + ".log";

    // 检查当前日志文件大小
    QFile file(m_currentLogFile);
    if (file.exists()) {
        QFileInfo fileInfo(file);
        if (fileInfo.size() > m_maxLogSize * 1024 * 1024) {
            // 日志文件超过最大大小，进行轮转
            QString newFileName = m_logDir + "system_" +
                dateStr + "_" + QDateTime::currentDateTime().toString("hhmmss") + ".log";
            file.rename(newFileName);
        }
    }
}

QString LogClass::logTypeToString(LogType type) const
{
    switch (type) {
        case SYSTEM_LOG: return "system";
        case OPERATION_LOG: return "operation";
        case ALARM_LOG: return "alarm";
        case EXCEPTION_LOG: return "exception";
        default: return "unknown";
    }
}

QString LogClass::logLevelToString(LogLevel level) const
{
    switch (level) {
        case INFO: return "INFO";
        case WARNING: return "WARNING";
        case ERR: return "ERROR";
        case CRITICAL: return "CRITICAL";
        default: return "UNKNOWN";
    }
}

void LogClass::writeToFile(const QString& logLine)
{
    QFile file(m_currentLogFile);
    if (file.open(QIODevice::Append | QIODevice::Text)) {
        QTextStream out(&file);
        out << logLine << "\n";
        file.close();
    }
}

void LogClass::log(SqliteManage *m_pSqliteManage,LogType type, LogLevel level, const QString& content, int userId, int deviceId)
{
    QMutexLocker locker(&m_mutex);

    // 检查并轮转日志文件
    checkAndRotateLogFile();

    // 获取当前时间
    QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");

    // 构建日志行
    QString logLine = QString("[%1] [%2] [%3] %4")
        .arg(timestamp)
        .arg(logLevelToString(level))
        .arg(logTypeToString(type))
        .arg(content);

    // 写入日志文件
    writeToFile(logLine);

    // 写入数据库
    QSqlQuery query(m_pSqliteManage->getDB());
    query.prepare(
        "INSERT INTO system_logs (timestamp, log_type, log_level, content, user_id, device_id) "
        "VALUES (:timestamp, :log_type, :log_level, :content, :user_id, :device_id)"
    );
    query.bindValue(":timestamp", timestamp);
    query.bindValue(":log_type", logTypeToString(type));
    query.bindValue(":log_level", logLevelToString(level));
    query.bindValue(":content", content);
    query.bindValue(":user_id", userId == -1 ? QVariant(QVariant::Int) : userId);
    query.bindValue(":device_id", deviceId == -1 ? QVariant(QVariant::Int) : deviceId);
    qDebug() << "Bound values before execution:" << query.boundValues();
    if (!query.exec()) {
        qDebug() << "Failed to insert log:" << query.lastError().text();
    }
    qDebug()<<"日志写入成功";
}

void LogClass::systemLog(SqliteManage *m_pSqliteManage,LogLevel level, const QString& content)
{
    log(m_pSqliteManage,SYSTEM_LOG, level, content);
}

void LogClass::operationLog(SqliteManage *m_pSqliteManage,LogLevel level, const QString& content, int userId)
{
    log(m_pSqliteManage,OPERATION_LOG, level, content, userId);
}

void LogClass::alarmLog(SqliteManage *m_pSqliteManage,LogLevel level, const QString& content, int deviceId)
{
    log(m_pSqliteManage,ALARM_LOG, level, content, -1, deviceId);
}

void LogClass::exceptionLog(SqliteManage *m_pSqliteManage,LogLevel level, const QString& content)
{
    log(m_pSqliteManage,EXCEPTION_LOG, level, content);
}

QVector<QVector<QVariant>> LogClass::queryLogs( SqliteManage *m_pSqliteManage,
                                                const QDateTime& startTime,
                                                const QDateTime& endTime,
                                                LogType type,
                                                const QString& keyword)
{
    QVector<QVector<QVariant>> result;

        QSqlQuery query(m_pSqliteManage->getDB());
        QString sql = QString("SELECT * FROM system_logs WHERE timestamp BETWEEN '%1' AND '%2'")
                .arg(startTime.toString("yyyy-MM-dd hh:mm:ss"))
                .arg(endTime.toString("yyyy-MM-dd hh:mm:ss"));

        if (type == SYSTEM_LOG|| type == OPERATION_LOG || type == ALARM_LOG ||type == EXCEPTION_LOG) {
            sql += " AND log_type = :logType";
        }

        if (!keyword.isEmpty()) {
            sql += " AND content LIKE :keyword";
        }

        sql += " ORDER BY timestamp DESC";

        // 预处理SQL语句
        if (!query.prepare(sql)) {
            qDebug() << "SQL prepare failed:" << query.lastError().text();
            return result;
        }

        if (type == SYSTEM_LOG|| type == OPERATION_LOG || type == ALARM_LOG ||type == EXCEPTION_LOG) {
            query.bindValue(":logType",logTypeToString(type));
        }

        if (!keyword.isEmpty()) {
            query.bindValue(":keyword", "%" + keyword + "%");
        }

        // 执行查询
        if (query.exec()) {
            qDebug()<<sql;
            while (query.next()) {
                QVector<QVariant> row;
                row.append(query.value("log_id"));
                row.append(query.value("timestamp"));
                row.append(query.value("log_type"));
                row.append(query.value("log_level"));
                row.append(query.value("content"));
                row.append(query.value("user_id"));
                row.append(query.value("device_id"));
                result.append(row);
            }
        } else {
            qDebug() << "Query execution failed:" << query.lastError().text();
        }

        return result;
}



bool LogClass::exportLogs(SqliteManage *m_pSqliteManage,
                          const QString& filePath,
                          const QDateTime& startTime,
                          const QDateTime& endTime,
                          LogType type,
                          const QString& keyword,
                          bool isCsv)
{
    QVector<QVector<QVariant>> logs = queryLogs(m_pSqliteManage,startTime, endTime, type, keyword);

    if (logs.isEmpty()) {
        return false;
    }

    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return false;
    }

    QTextStream out(&file);
    out.setCodec("UTF-8");

    // 写入表头
    if (isCsv) {
        out << "日志ID,时间戳,日志类型,日志等级,日志内容,用户ID,设备ID\n";
    } else {
        out << "日志ID\t时间戳\t日志类型\t日志等级\t日志内容\t用户ID\t设备ID\n";
    }

    // 写入数据
    for (const auto& row : logs) {
        QString line;
        for (int i = 0; i < row.size(); ++i) {
            QString value = row[i].toString();
            if (isCsv) {
                // 处理CSV中的引号和逗号
                if (value.contains(",") || value.contains("\"")) {
                    value = "\"" + value.replace("\"", "\"\"") + "\"";
                }
                line += value + (i < row.size() - 1 ? "," : "\n");
            } else {
                line += value + (i < row.size() - 1 ? "\t" : "\n");
            }
        }
        out << line;
    }

    file.close();
    return true;
}
